package com.gict.antifraudback.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gict.antifraudback.constants.RedisKeyConstants;
import com.gict.antifraudback.entity.Article;
import com.gict.antifraudback.entity.User;
import com.gict.antifraudback.exception.BusinessException;
import com.gict.antifraudback.exception.MyException;
import com.gict.antifraudback.jwt.JWTData;
import com.gict.antifraudback.jwt.JwtUtil;
import com.gict.antifraudback.mapper.UserMapper;
import com.gict.antifraudback.redis.RedisService;
import com.gict.antifraudback.result.ResultEnum;
import com.gict.antifraudback.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    protected JWTData jwtData;
    @Autowired
    private RedisService redisService;

    private static final ObjectMapper MAPPER = new ObjectMapper();

    /**
     * @param token
     * @return
     */
    @Override
    public User backQueryUserByToken(String token) {
        Integer id = JwtUtil.getUniqueId(jwtData, token, "login");

        String loginKey = String.format(RedisKeyConstants.BACK_LOGIN_KEY, id);
        token = redisService.get(loginKey);
        if (token == null){
            throw new MyException(ResultEnum.CODE_403);
        }

        User user = userMapper.selectById(id);
        serUserFieldArray(user);
        return user;
    }

    @Override
    public User frontQueryUserByToken(String token) {
        Integer id = JwtUtil.getUniqueId(jwtData, token, "login");

        String loginKey = String.format(RedisKeyConstants.FRONT_LOGIN_KEY, id);
        token = redisService.get(loginKey);
        if (token == null){
            throw new MyException(ResultEnum.CODE_403);
        }

        User user = userMapper.selectById(id);
        serUserFieldArray(user);
        return user;
    }

    /**
     * 这里数据库设置的json需要手动反序列化设置用户参数
     *
     * @param user
     */
    private void serUserFieldArray(User user) {
        if (user.getAbility() != null) {
            user.setAbilityArray(JSON.parseArray(user.getAbility()));
        }
        if (user.getRoles() != null) {
            user.setRolesArray(JSON.parseArray(user.getRoles()));
        }
    }

    @Override
    public String crateBackToken(Integer id) {
        String token = JwtUtil.createJWT("login",
                id,
                jwtData.getClientId(),
                jwtData.getName(),
                jwtData.getExpiresSecond(),
                jwtData.getBase64Secret());
        String loginKey = String.format(RedisKeyConstants.BACK_LOGIN_KEY, id);
        redisService.set(loginKey, token, jwtData.getExpiresSecond() / 1000);// 两小时过期
        return token;
    }

    @Override
    public String crateFrontToken(Integer id) {
        String token = JwtUtil.createJWT("login",
                id,
                jwtData.getClientId(),
                jwtData.getName(),
                jwtData.getExpiresSecond(),
                jwtData.getBase64Secret());
        String loginKey = String.format(RedisKeyConstants.FRONT_LOGIN_KEY, id);
        // 每次登录都需要重新设置token
        redisService.set(loginKey, token, jwtData.getExpiresSecond() / 1000);
        return token;
    }

    @Override
    public User login(String username, String password) {
        User user = userMapper.login(username, password);
        if (user == null) {
            throw new MyException(ResultEnum.CODE_4);
        }
        serUserFieldArray(user);
        return user;
    }

    @Override
    public User forntLogin(String email, String password) {
        User user = userMapper.forntLogin(email, password);
        if (user == null) {
            throw new MyException(ResultEnum.CODE_4);
        }
        serUserFieldArray(user);
        return user;
    }

    @Override
    public User getByEmail(String email) {
        LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(User::getEmail, email);
        return getOne(wrapper);
    }

    @Override
    public void setUserName(List<Article> records) {
        if (records.isEmpty()){
            return;
        }
        // 设置作者名称
        List<Integer> userIds = records.stream().map(Article::getUserId).collect(Collectors.toList());
        Collection<User> users = listByIds(userIds);
        if (!users.isEmpty()) {
            Map<Integer, User> menuMap = users.stream().collect(Collectors.toMap(User::getId, a -> a, (a, b) -> a));
            for (Article record : records) {
                User user = menuMap.get(record.getUserId());
                if (user != null) {
                    record.setUserName(user.getName());
                }
            }
        }
    }
}